

#ifndef __COMM_MAP_H__
#define __COMM_MAP_H__

#include "comm/comm_car.h"
#include "comm/comm_base.h"
#include "comm/comm_file.h"
#include <iostream>
#include <list>
#include <vector>

using namespace std;

/**************************************************************************************
功能描述: 读取yaml文件
          yaml文件有专门的插件可以读入和写出，此处用得比较简单，按固定格式读取即可。
          限制:
            每一项必须单独为一行
            每一行最长1K
修改记录:
**************************************************************************************/
#define SIMPLE_YAML_FILE_MAX_ITEM_LEN   1024

typedef struct {
    const char *pStrTag;
    char strContent[SIMPLE_YAML_FILE_MAX_ITEM_LEN];     /* tag:之后的内容，不含空格 */
} YAML_FILE_ITEM_STRU;

class SIMPLE_YAML_FILE_C
{
public:
    SIMPLE_YAML_FILE_C(const char *pcYamlFileName);

    int ReadItem(YAML_FILE_ITEM_STRU astItem[], int itemNum);
    int WriteItem(YAML_FILE_ITEM_STRU astItem[], int itemNum);
private:
    string strFileName_;

    void DelAllCharInStr(char *pcStr, char delChar);
    bool IsStrBeginWith(const char *pcStr, const char *pcSubStr);
    YAML_FILE_ITEM_STRU *MatchItem(YAML_FILE_ITEM_STRU astItem[], int itemNum, const char *pstrLine);
    int ReadItemFromFile(YAML_FILE_ITEM_STRU astItem[], int itemNum);
};

class MAP_YAML_FILE_C
{
public:
    int  Read(const string &strMapPath, string &strPgmFileName, float &resolution, COORDINATE_2D_STRU &stOriginPos) const;
    int  Write(const string &strMapPath, float resolution, const COORDINATE_2D_STRU &stOriginPos) const;

private:
    void GetYamlFilePath(const string &strMapPath, string &strYamlFilePath) const;
    void GetPgmFileName(const string &strMapPath, string &strPgmFileName) const;
};

class PGM_FILE_C
{
public:
    PGM_FILE_C(void);
    virtual ~PGM_FILE_C(void);

    int  ReadImageSize(const string &strMapPath, unsigned int &imageCols, unsigned int &imageRows);
    int  ReadImage(const string &strMapPath, unsigned char *pucImage, unsigned int imageMaxSize);

    void SaveFile(const string &strMapPath, unsigned char *pucImage, unsigned int imageCols, unsigned int imageRows);
private:
    void GetPgmFilePath(const string &strMapPath, string &strPgmFilePath);

    int ReadNextLine(FILE *pfRead, char *pucLine, int maxLineLen);
    int ReadFileHead(FILE *pfRead, unsigned int &imageCols, unsigned int &imageRows);
};

/**************************************************************************************
功能描述: 灰度图像类
          该图像主要用于地图处理，所以图像行序是上下颠倒的
修改记录:
**************************************************************************************/
class GRAY_IMAGE_C
{
public:
    GRAY_IMAGE_C(void);
    virtual ~GRAY_IMAGE_C(void);

    INT32 CreateImage(UINT32 sizeX, UINT32 sizeY);
    INT32 CreateImage(UINT32 sizeX, UINT32 sizeY, UINT08 defaultVal);
    INT32 CreateImage(UINT32 sizeX, UINT32 sizeY, UINT08 *pucImage);
    INT32 ResizeImage(const IMAGE_COORDINATE_STRU &stNewMapSize, const IMAGE_COORDINATE_STRU &stNewMapLeftButtCoordByOld, UINT08 defaultVal);
    INT32 CopyImage(const GRAY_IMAGE_C &objSrcImage, const IMAGE_COORDINATE_STRU &stSrcLeftButtCoord, const IMAGE_COORDINATE_STRU &stCopySize);
    INT32 CopyImage(const GRAY_IMAGE_C &objSrcImage);
    INT32 LoadImage(const string &strMapPath);
    INT32 SaveImage(const string &strMapPath) const;
    void  FreeImage(void);
    void  SwapImage(GRAY_IMAGE_C &objOtherImage);
    INT32 GetImageSize(UINT32 &sizeX, UINT32 &sizeY) const;

protected:
    bool IsImageValid(void) const;
    bool isCoordValid(int cellX, int cellY) const;
    bool isCoordValid(const IMAGE_COORDINATE_STRU &stCoord) const;

    UINT32 GetImageSizeX(void) const;
    UINT32 GetImageSizeY(void) const;
    void   GetLBCoord(IMAGE_COORDINATE_STRU &stLBCoord) const;
    void   GetRTCoord(IMAGE_COORDINATE_STRU &stRTCoord) const;
    INT32  TransSrcImageCoordToLoc(const IMAGE_COORDINATE_STRU &stSrcImageCoord, IMAGE_COORDINATE_STRU &stLocImageCoord);

    void  SetImage(unsigned char setVal);
    void  SetImage(const IMAGE_COORDINATE_STRU &stAreaLeftButtCoord, UINT32 areaSizeX, UINT32 areaSizeY, UINT08 *pucMapArea);
    void  SetCell(int coordX, int coordY, unsigned char setVal);
    void  SetCell(IMAGE_COORDINATE_STRU *pstCoord, unsigned char setVal);
    void  SetAreaOfSameColor(const IMAGE_COORDINATE_STRU &stRefPixel, UINT08 newColor);
    INT32 SetLeftAndRightPixelsOfLine(const vector<IMAGE_COORDINATE_STRU> &vectLine, UINT08 setLeftVal, UINT08 setRightVal, UINT08 splitVal, UINT32 maxStepLen);

    INT32   GetCell(int cellX, int cellY, UINT08 &cellVal) const;
    UINT08 *GetCellPtr(int cellX, int cellY) const;
    INT32   GetCellsInArea(UINT08 cellVal, const IMAGE_COORDINATE_STRU &stAreaLBCoord, const IMAGE_COORDINATE_STRU &stAreaSize, vector<IMAGE_COORDINATE_STRU> &vectCellList) const;

private:
    unsigned int   mapSizeX_;                           /* 图像X方向大小，即像素列数 */
    unsigned int   mapSizeY_;                           /* 图像Y方向大小，即像素行数 */
    unsigned char *pucMap_;                             /* 图像内存地址 */

    void TurnMapUpsideDown(unsigned char *pucSrcMap, unsigned char *pucTgtMap) const;
};

class GRAY_MAP_C : public GRAY_IMAGE_C
{
public:
    GRAY_MAP_C(void);
    virtual ~GRAY_MAP_C(void);

    BOOL IsValid(void) const;

    int    GetMapInfo(const string &strMapPath, string &strMapPgmNameFrmYaml, IMAGE_COORDINATE_STRU &stMapSize, COORDINATE_2D_STRU &stOriginPos);
    int    GetMapInfo(COORDINATE_2D_STRU &stOriginPos, float &resolution, UINT32 &sizeX, UINT32 &sizeY, UINT08 **ppucMap) const;
    void   GetMapSize(IMAGE_COORDINATE_STRU &stSize) const;
    void   GetMapSize(COORDINATE_2D_STRU &stSize) const;
    INT32  GetMapSize(void) const;
    int    TransPictureCoordToPos(IMAGE_COORDINATE_STRU &stPictureCoord, COORDINATE_2D_STRU &stMapPos);
    void   ConvPosToMapCoord(const COORDINATE_2D_STRU *pstPos, IMAGE_COORDINATE_STRU *pstCoord) const;

    UINT08 GetCostOfObst(void) const;
    UINT08 GetCostOfNull(void) const;
    UINT08 GetCostOfLeft(void) const;
    UINT08 GetCostOfRight(void) const;

    int    LoadMap(const string &strMapPath, bool isExistYamlFile = true);
    int    SaveMap(const string &strMapPath) const;

    INT32 CreateMap(const COORDINATE_2D_STRU &stOriginPos, UINT32 mapSizeX, UINT32 mapSizeY, BOOL isDefaultNull = false, float resolution = MAP_RESOLUTION);
    int   CreateMap(const COORDINATE_2D_STRU &stLeftButtomPoint, const COORDINATE_2D_STRU &stRightTopPoint, BOOL isDefaultNull = false, float resolution = MAP_RESOLUTION);
    int   CreateMap(UINT32 mapSizeX, UINT32 mapSizeY, UINT08 *pucImage);
    INT32 CreateMap(UINT32 mapSizeX, UINT32 mapSizeY, UINT08 defaultVal, float resolution = MAP_RESOLUTION);
    INT32 ResizeMap(COORDINATE_2D_STRU &stLeftButtomPoint, COORDINATE_2D_STRU &stRightTopPoint, BOOL isDefaultNull = false);
    INT32 CopyMap(const GRAY_MAP_C &objSrcMap, const COORDINATE_2D_STRU &stLeftButtomPoint, const COORDINATE_2D_STRU &stRightTopPoint);
    INT32 CopyMap(const GRAY_MAP_C &objSrcMap);
    void  DeleteMap(void);
    void  SwapMap(GRAY_MAP_C &objOtherMap);

    void  SetCellByPos(const COORDINATE_2D_STRU &stPos, unsigned char setVal);
    void  SetCellsByPos(const list<COORDINATE_2D_STRU> &posLst, unsigned char setVal);
    void  SetCellsByPos(const vector<COORDINATE_2D_STRU> &vectPos, UINT08 setVal);
    void  SetCellsOfRectangleIncludingQuadrangle(const COORDINATE_2D_STRU &stVertice1, const COORDINATE_2D_STRU &stVertice2, const COORDINATE_2D_STRU &stVertice3, const COORDINATE_2D_STRU &stVertice4, UINT08 setVal);
    void  SetCellsOfLineSegment(const COORDINATE_2D_STRU &stPoint1, const COORDINATE_2D_STRU &stPoint2, UINT08 setVal, vector<IMAGE_COORDINATE_STRU> *pvectSetPoint = NULL, BOOL isSetEnd = true);
    void  SetCellsOfLine(const vector<COORDINATE_2D_STRU> &vectLine, UINT08 setVal, vector<IMAGE_COORDINATE_STRU> *pvectSetPoint = NULL, UINT32 beginIdx = 0, UINT32 endIdx = UINT32_NULL, BOOL isSetEnd = false);
    void  SetCellsOfSameCostArea(const COORDINATE_2D_STRU &stRefPos, UINT08 setVal);
    INT32 SetLeftAndRightAreaOfLine(const vector<COORDINATE_2D_STRU> &vectLine, float areaDist, UINT32 splitLineSize);
    void  SetCellsOfCircle(const COORDINATE_2D_STRU &stCenterPos, float radius, UINT08 setVal);
    void  SetMap(UINT08 setVal);
    void  SetMap(const COORDINATE_2D_STRU &stLeftButtPoint, UINT32 mapSizeX, UINT32 mapSizeY, UINT08 *pucMap);
    void  SetMapNull(void);
    void  SetOrigin(const COORDINATE_2D_STRU &stOrigin);

    BOOL  IsCellsOfLinSegAllNull(const COORDINATE_2D_STRU &stPoint1, const COORDINATE_2D_STRU &stPoint2) const;

    UINT08 GetCellByPos(const COORDINATE_2D_STRU &stPos) const;
    INT32  GetOverlapArea(const AREA_C &objSrcArea, AREA_C &objOverlapArea) const;
    INT32  GetCellsPosListInArea(const AREA_C &objArea, UINT08 cellCost, vector<COORDINATE_2D_STRU> &vectCellsPosList) const;

    int  Merge(COORDINATE_2D_STRU &stTgtLeftButtomPoint, GRAY_MAP_C &objSrc, COORDINATE_2D_STRU &stSrcLeftButtomPoint, COORDINATE_2D_STRU &stSrcRightTopPoint);
    int  GetEffectArea(COORDINATE_2D_STRU &stLeftButtomPoint, COORDINATE_2D_STRU &stRightTopPoint);
    void FilterObstOutlier(UINT32 filterRange, UINT32 filterLowerCount);

protected:
    static const UINT08 cellCostObst_            = 0;
    static const UINT08 cellCostOver_            = 1;
    static const UINT08 cellCostCarBodyTrc_      = 200;
    static const UINT08 cellCostUnknown_         = 205;
    static const UINT08 cellCostNearVirtualObst_ = 220;
    static const UINT08 cellCostVirtualObst_     = 230;
    static const UINT08 cellCostNull_            = 254;
    static const UINT08 cellCostLeftArea_        = 180;
    static const UINT08 cellCostRightArea_       = 160;
    static const UINT08 cellCostSplitLine        = 170;

    UINT08  GetCellCost(int cellX, int cellY) const;
    UINT08  GetCellCost(const IMAGE_COORDINATE_STRU &stCellCoord) const;
    void    GetRTPoint(COORDINATE_2D_STRU &stRTPoint) const;

    void    GetCellsOfLineSeg(const COORDINATE_2D_STRU &stPoint1, const COORDINATE_2D_STRU &stPoint2, vector<IMAGE_COORDINATE_STRU> &vctCells) const;

    void ConvPosToMapCoord(const COORDINATE_2D_STRU *pstOriginPos, const COORDINATE_2D_STRU *pstPos, IMAGE_COORDINATE_STRU *pstCoord) const;
    void ConvMapCoordToPos(const IMAGE_COORDINATE_STRU &stCoord, COORDINATE_2D_STRU &stPos) const;
    float CalcDistByCoordDiff(int diffX, int diffY);
    unsigned int GetCoorDist(float dist);
    int Calc2CellDistSqu(int cell1X, int cell1Y, int cell2X, int cell2Y);

private:
    COORDINATE_2D_STRU stOriginPos_;
    float              imageResolution_;

    int  CalcMapInfo(const COORDINATE_2D_STRU &stLeftButtomPoint, const COORDINATE_2D_STRU &stRightTopPoint, COORDINATE_2D_STRU &stOriginPos, UINT32 &sizeX, UINT32 &sizeY);

    bool   IsCellEffect(int cellX, int cellY);
    bool   IsObstOutlier(int cellX, int cellY, int range, int judgeLowerCount);
    void   GetNearCellInfo(int cellX, int cellY, bool &isNearExistUnknown, bool &isNearExistNull, bool &isNearExistObst);
    UINT08 GetAbnormalCellCorrect(UINT08 cellCost, int cellX, int cellY);
};

/**************************************************************************************
功能描述: 车体轨迹地图
修改记录:
**************************************************************************************/
class TRC_MAP_C : public GRAY_MAP_C
{
public:
    INT32 Reset(const COORDINATE_2D_STRU &stRouteAreaLeftButtPoint, const COORDINATE_2D_STRU &stRouteAreaRightTopPoint);

    BOOL  Is4SideAreaPassable(const COORDINATE_2D_STRU &stLeftFront, const COORDINATE_2D_STRU &stRightFront, const COORDINATE_2D_STRU &stLeftBack, const COORDINATE_2D_STRU &stRightBack) const;
    BOOL  IsAllAreaPassable(const COORDINATE_2D_STRU &stLeftFront, const COORDINATE_2D_STRU &stRightFront, const COORDINATE_2D_STRU &stLeftBack, const COORDINATE_2D_STRU &stRightBack) const;

    void  SetCarBodyArea(const COORDINATE_2D_STRU &stLeftFront, const COORDINATE_2D_STRU &stRightFront, const COORDINATE_2D_STRU &stLeftBack, const COORDINATE_2D_STRU &stRightBack, BOOL isNeedClr = true);
    void  ClearCarBodyArea(void);

    void  SaveTrcMap(const string &strMapPath);
    BOOL  IsTrcMapValid(void) const;

    BOOL  IsInTrcArea(const COORDINATE_2D_STRU &stPoint) const ;

    BOOL  IsCellObst(int cellX, int cellY) const;
private:
    vector<IMAGE_COORDINATE_STRU> stGoForwardTrcPoint_;
};

#endif

